package com.yfp.client.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfp.client.domain.*;
import com.yfp.client.domain.*;
import com.yfp.client.domain.vo.LotteryRecordVO;
import com.yfp.client.domain.vo.LotteryVO;
import com.yfp.client.domain.vo.PrizeListVO;
import com.yfp.client.mapper.*;
import com.yfp.client.mapper.*;
import com.yfp.client.service.LotteryRecordsService;
import com.yfp.client.service.MarCouponPackDetailsService;
import com.yfp.client.service.MarCouponService;
import com.yfp.client.util.SecurityUtils;
import com.yfp.common.core.constant.CacheConstants;
import com.yfp.common.core.exception.ServiceException;
import com.yfp.common.core.utils.DateUtils;
import com.yfp.operation.api.RemoteOperationService;
import com.yfp.operation.domain.WinningGrantDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.*;
import java.util.*;

/**
* @author admin
* @description 针对表【lottery_records(抽奖主表)】的数据库操作Service实现
* @createDate 2025-01-03 09:41:02
*/
@Service
@Slf4j
public class LotteryRecordsServiceImpl extends ServiceImpl<LotteryRecordsMapper, LotteryRecords> implements LotteryRecordsService{

    @Resource
    private LotteryRecordsRewardMapper lotteryRecordsRewardMapper;
    @Resource
    private LotteryRecordsMapper lotteryRecordsMapper;
    @Resource
    private LotteryRecordsClientRecordsMapper lotteryRecordsClientRecordsMapper;
    @Resource
    private ClientMapper clientMapper;
    @Resource
    private RemoteOperationService remoteOperationService;
    @Resource
    private OrderComboMapper orderComboMapper;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private MarCouponPackDetailsService marCouponPackDetailsService;
    @Resource
    private MarCouponService marCouponService;
    @Resource
    private ClientCouponMapper clientCouponMapper;
    @Resource
    private ClientLotteryNumMapper clientLotteryNumMapper;
    @Resource
    private MarCouponPackMapper marCouponPackMapper;


    /**
     * 奖品列表
     * @return
     */
    @Override
    public LotteryVO prizeList(String cityName) {
//        String cityName = SecurityUtils.getCityName();
        LotteryVO lotteryVO = lotteryRecordsMapper.getActivityRule(cityName);
        if (BeanUtil.isEmpty(lotteryVO)) {
            return lotteryVO;
        }

        // 获取当前日期
        LocalDate today = LocalDate.now();
        // 获取当天的开始时间（零点）
        LocalDateTime startOfDay = today.atStartOfDay();
        Instant instant = startOfDay.atZone(ZoneId.systemDefault()).toInstant();
        Date startTime = Date.from(instant);

        // 获取当天的结束时间（23:59:59.999999999）
        LocalDateTime endOfDay = today.atTime(LocalTime.MAX);
        Instant instant1 = endOfDay.atZone(ZoneId.systemDefault()).toInstant();
        Date endTime = Date.from(instant1);

        // 当日抽奖次数
        Integer todayLotteryCount = lotteryRecordsClientRecordsMapper.timeLotteryCount(startTime,endTime,lotteryVO.getLotteryId(),SecurityUtils.getClientId());
        // 活动开始到现在抽奖次数
        Integer startLotteryCount = lotteryRecordsClientRecordsMapper.timeLotteryCount(lotteryVO.getStartTime(),endTime,lotteryVO.getLotteryId(),SecurityUtils.getClientId());

//        // 当日抽奖次数
//        Integer todayLotteryCount = lotteryRecordsClientRecordsMapper.timeLotteryCount(startTime,endTime,lotteryId,"152");
//        // 活动开始到现在抽奖次数
//        Integer startLotteryCount = lotteryRecordsClientRecordsMapper.timeLotteryCount(lotteryRecords.getStartTime(),endTime,lotteryId,"152");

        lotteryVO.setCanLottery(true);

        if (lotteryVO.getConditionEverydayLottery() <= todayLotteryCount) {
            lotteryVO.setCanLottery(false);
        }
        if (lotteryVO.getConditionTotalLottery() <= startLotteryCount) {
            lotteryVO.setCanLottery(false);
        }


        List<PrizeListVO> list = lotteryRecordsRewardMapper.prizeList(cityName);
        BigDecimal reduce = list.stream().map(PrizeListVO::getRewardProbability)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        if (reduce.compareTo(BigDecimal.valueOf(100)) == 0) {
            lotteryVO.setIsso(true);
        } else {
            lotteryVO.setIsso(false);
        }
        lotteryVO.setPrizeListVOs(list);
        LambdaQueryWrapper<ClientLotteryNum> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ClientLotteryNum::getClientId, SecurityUtils.getClientId());
        wrapper.eq(ClientLotteryNum::getLotteryRecordsId, lotteryVO.getLotteryId());
        ClientLotteryNum clientLotteryNum = clientLotteryNumMapper.selectOne(wrapper);
        lotteryVO.setLotteryNum(0);
        if (!BeanUtil.isEmpty(clientLotteryNum)) {
            lotteryVO.setLotteryNum(clientLotteryNum.getLotteryNum());
        }
        return lotteryVO;
    }


    /**
     * 抽奖记录
     * @param lotteryId
     * @return
     */
    @Override
    public List<LotteryRecordVO> lotteryRecord(Long lotteryId, Date getTime) {
        String clientId = SecurityUtils.getClientId();
//        String clientId = "152";

        List<Long> lrcrIds = lotteryRecordsClientRecordsMapper.lotteryRecord(clientId,lotteryId,getTime);

        if (CollUtil.isEmpty(lrcrIds)) {
            return new ArrayList<>();
        }

        List<LotteryRecordVO> list1 = clientCouponMapper.lotteryRecord(lrcrIds);
        return list1;
    }


    /**
     * 抽奖
     * @return
     */
    @Override
    @Transactional
    public LotteryRecordVO lottery(Long lotteryId) {

        LotteryRecords lotteryRecords = lotteryRecordsMapper.selectById(lotteryId);

        // 获取当前日期
        LocalDate today = LocalDate.now();

        // 获取当天的开始时间（零点）
        LocalDateTime startOfDay = today.atStartOfDay();
        Instant instant = startOfDay.atZone(ZoneId.systemDefault()).toInstant();
        Date startTime = Date.from(instant);

        // 获取当天的结束时间（23:59:59.999999999）
        LocalDateTime endOfDay = today.atTime(LocalTime.MAX);
        Instant instant1 = endOfDay.atZone(ZoneId.systemDefault()).toInstant();
        Date endTime = Date.from(instant1);

        // 当日抽奖次数
        Integer todayLotteryCount = lotteryRecordsClientRecordsMapper.timeLotteryCount(startTime,endTime,lotteryId,SecurityUtils.getClientId());
        // 活动开始到现在抽奖次数
        Integer startLotteryCount = lotteryRecordsClientRecordsMapper.timeLotteryCount(lotteryRecords.getStartTime(),endTime,lotteryId,SecurityUtils.getClientId());

//        // 当日抽奖次数
//        Integer todayLotteryCount = lotteryRecordsClientRecordsMapper.timeLotteryCount(startTime,endTime,lotteryId,"152");
//        // 活动开始到现在抽奖次数
//        Integer startLotteryCount = lotteryRecordsClientRecordsMapper.timeLotteryCount(lotteryRecords.getStartTime(),endTime,lotteryId,"152");



        if (lotteryRecords.getConditionEverydayLottery() <= todayLotteryCount) {
            throw new ServiceException("“您已达到今日抽奖次数上限，明天再来试试手气吧！”");
        }
        if (lotteryRecords.getConditionTotalLottery() <= startLotteryCount) {
            throw new ServiceException("“您已达到抽奖次数上限！”");
        }


        // 获取奖品列表
        List<LotteryRecordVO> list = lotteryRecordsRewardMapper.selectPrizeByLotteryId(lotteryId);

        for (LotteryRecordVO recordVO : list) {
            recordVO.setAcquireTime(new Timestamp(System.currentTimeMillis()));
            if (null != recordVO.getValidDays()) {
                // 当前日期
                LocalDate currentDate = LocalDate.now();
                // 要添加的天数
                int daysToAdd = recordVO.getValidDays();
                // 当前日期加上指定天数
                LocalDate newDate = currentDate.plusDays(daysToAdd);
                // 获取结果日期的起始时间（00:00:00）
                LocalDateTime startDay = newDate.atStartOfDay();
                LocalDateTime localDateTime = startDay.minusSeconds(1);
                // 转换为Instant
                Instant ins = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
                // 转换为Timestamp
                Timestamp timestamp = Timestamp.from(ins);
                recordVO.setValidityTime(timestamp);
            }
        }

        list.sort(Comparator.comparing(LotteryRecordVO::getRewardProbability));

        Random random = new Random();
        int randomNumber = random.nextInt(10000);

        int sum = 0;
        LotteryRecordVO lotteryRecordVO = new LotteryRecordVO();
        WinningGrantDTO winningGrantDTO = new WinningGrantDTO();
        winningGrantDTO.setLotteryId(lotteryId);
        winningGrantDTO.setClientId(SecurityUtils.getClientId());
//        winningGrantDTO.setClientId("152");
        for (LotteryRecordVO reward : list) {
            sum += reward.getRewardProbability().multiply(BigDecimal.valueOf(100)).intValue();
            if (randomNumber < sum) {
                winningGrantDTO.setLrrId(reward.getLrrId());
                winningGrantDTO.setWinning(true);
                winningGrantDTO.setDistributionQuantity(reward.getDistributionQuantity());
                if (reward.getType() == 6) {
                    winningGrantDTO.setType(3);
                } else if (reward.getType() == 88) {
                    winningGrantDTO.setType(2);
                } else {
                    winningGrantDTO.setType(1);
                }


                reward.setWinPopupImageUrl(lotteryRecords.getWinPopupImageUrl());
                reward.setWinPopupBtn(lotteryRecords.getWinPopupBtn());
                lotteryRecordVO = reward;
                break;
            }
        }

        // 未中奖
        if (BeanUtil.isEmpty(lotteryRecordVO)) {
            winningGrantDTO.setWinning(false);
            lotteryRecordVO.setLosePopupText(lotteryRecords.getLosePopupText());
            lotteryRecordVO.setLosePopupImageUrl(lotteryRecords.getLosePopupImageUrl());
            lotteryRecordVO.setLosePopupBtn(lotteryRecords.getLosePopupBtn());
        }

        // 抽奖次数-1
        clientLotteryNumMapper.updateLotteryNum(SecurityUtils.getClientId(),lotteryId);
//        clientMapper.updateLotteryNum("152");
        Boolean aBoolean = winningGrant(winningGrantDTO);
        lotteryRecordVO.setIsGain(aBoolean);
        log.info("返回参数:{}",lotteryRecordVO);
        return lotteryRecordVO;
    }


    public Boolean winningGrant(WinningGrantDTO winningGrantDTO){
        LotteryRecordsClientRecords records = new LotteryRecordsClientRecords();
        records.setClientId(winningGrantDTO.getClientId());
        records.setRewardType(winningGrantDTO.getType());
        records.setLotteryRecordsId(winningGrantDTO.getLotteryId());
        records.setLotteryRecordsWinId(winningGrantDTO.getLrrId());

        // 获取点位信息
        String positionId = orderComboMapper.getPositionId(winningGrantDTO.getClientId());
        records.setPositionId(positionId);

        if (!winningGrantDTO.isWinning()) {
            records.setRewardFlag(0);
            lotteryRecordsClientRecordsMapper.add(records);
            return true;
        }

        RLock lock = redissonClient.getLock(CacheConstants.LOTTERY_PRIZE_REMAINING_STOCK_LOCK_KEY + winningGrantDTO.getLrrId());
        boolean b = lock.tryLock();
        Assert.isTrue(b, "稍后重试");

        LotteryRecordsReward reward = lotteryRecordsRewardMapper.selectById(winningGrantDTO.getLrrId());
        if (reward.getRemainingStock() <= 0) {
            records.setRewardFlag(0);
            lotteryRecordsClientRecordsMapper.add(records);
            return false;
        }
        try {

            LotteryRecordsReward lotteryRecordsReward = lotteryRecordsRewardMapper.selectById(winningGrantDTO.getLrrId());

            records.setRewardId(lotteryRecordsReward.getRewardId());
            records.setRewardFlag(1);
            records.setReceiveState(1);
            if (records.getRewardType() == 3) {
                records.setReceiveState(2);
            }
            lotteryRecordsClientRecordsMapper.add(records);

            if (lotteryRecordsReward.getRewardType() == 2) {
                MarCouponPack marCouponPack = marCouponPackMapper.findById(lotteryRecordsReward.getRewardId());
                if (1 == marCouponPack.getStatus()) {
                    List<MarCouponPackDetails> marCouponPackDetails = marCouponPackDetailsService.findByCouponPackId(lotteryRecordsReward.getRewardId());
                    int s = 0;
                    for (MarCouponPackDetails marCouponPackDetail : marCouponPackDetails) {
                        MarCoupon marCoupon = marCouponService.findById(marCouponPackDetail.getCouponId());
                        int a = 0;
                        for (int i = 0; i < marCouponPackDetail.getCouponCount(); i++) {
                            Long couponId = this.verifyCoupon(marCoupon.getId(), winningGrantDTO.getClientId(), lotteryRecordsReward.getRewardId(), lotteryRecordsReward.getLotteryRecordsId(), records.getId(), 1);// 礼包1  券2
                            if (couponId == null) {
                                a++;
                            }
                        }
                        // 校验该券有没有发放成功过，哪怕发了一张都不会增加s的数量
                        if (a == marCouponPackDetail.getCouponCount()) {
                            s++;
                        }
                    }
                    // 只有礼包中的优惠券都出现发不了的情况时，才会返回false
                    if (s == marCouponPackDetails.size()) {
                        return false;
                    }
                } else {
                    return false;
                }
            } else {
                MarCoupon marCoupon = marCouponService.findById(lotteryRecordsReward.getRewardId());
                for (int i = 0; i < lotteryRecordsReward.getDistributionQuantity(); i++) {
                    Long couponId = this.verifyCoupon(marCoupon.getId(), winningGrantDTO.getClientId(), lotteryRecordsReward.getRewardId(),lotteryRecordsReward.getRewardId(),records.getId(), 2);
                    if (couponId == null) {
                        return false;
                    }
                }
            }

            // 扣除剩余库存
            lotteryRecordsRewardMapper.updateRemainingStock(winningGrantDTO.getLrrId(),winningGrantDTO.getDistributionQuantity());

        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        } finally {
            lock.unlock();
        }
        return true;
    }


    /**
     * 抽中礼包发券
     *
     * @param couponId
     * @param clientId
     * @param couponPackId
     */
    public Long verifyCoupon(Long couponId, String clientId, Long couponPackId, Long lrrId, Long lrcrId, Integer type) { // 礼包1  券2
        RLock lock = redissonClient.getLock(CacheConstants.MAR_COUPON_SURPLUSCOUNT_LOCK_KEY + couponId);
        boolean b = lock.tryLock();
        Assert.isTrue(b, "稍后重试");

        try {

            MarCoupon marCoupon = marCouponService.findById(couponId);
            if (null != marCoupon.getValidDays() && marCoupon.getValidDays() != 0) {
                // 当前日期
                LocalDate currentDate = LocalDate.now();
                // 要添加的天数
                int daysToAdd = marCoupon.getValidDays();
                // 当前日期加上指定天数
                LocalDate newDate = currentDate.plusDays(daysToAdd);
                // 获取结果日期的起始时间（00:00:00）
                LocalDateTime startOfDay = newDate.atStartOfDay();
                LocalDateTime localDateTime = startOfDay.minusSeconds(1);
                Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
                // 转换为 Date
                Date date = Date.from(instant);
                marCoupon.setValidStartTime(new Date());
                marCoupon.setValidEndTime(date);
            }

            log.info("优惠券:{}", marCoupon);


            // 优惠券不存在
            if (null == marCoupon) {
                return null;
            }

            // 只校验礼包的
            if (marCoupon.getSurplusCount() <= 0 && type == 1) {
                log.info("优惠券库存不足");
                return null;
            }

            // 优惠券删除或者优惠券失效
            if (marCoupon.getStatus() == 0 || marCoupon.getStatus() == 2) {
                log.info("优惠券删除或者优惠券失效");
                return null;
            }
            // 优惠券是否过期
            Date date = DateUtils.addDays(marCoupon.getValidEndTime(), marCoupon.getPostponeDay());
            if (date.getTime() < System.currentTimeMillis()) {
                log.info("优惠券过期");
                return null;
            }

            // 最大领取
            int countCoupon = clientCouponMapper.countByClientIdAndCouponId(clientId, couponId, null);
            if (countCoupon >= marCoupon.getReceiveCount()) {
                log.info("超过最大领取数");
                return null;
            }
//        // 是否新用户
//        if (marCoupon.getClientStatus() == 2) {
//            Integer orderCount = orderComboService.countOrderByClientId(clientId);
//            if (orderCount > 0) {
//                return;
//            }
//        }

            ClientCoupon clientCoupon = new ClientCoupon();
            BeanUtils.copyProperties(marCoupon, clientCoupon);
            clientCoupon.setClientId(clientId);
            clientCoupon.setCouponId(couponId);
            clientCoupon.setLotteryRecordsClientRecordsId(lrcrId);
            clientCoupon.setSourceType(3);
            if (type == 1) {
                clientCoupon.setCouponPackId(couponPackId);
                marCouponService.editSurplusCount(couponId);
            }

            clientCouponMapper.insert(clientCoupon);
            return clientCoupon.getId();
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        } finally {
            lock.unlock();
        }
    }



}




